package mcp_tools

import (
	"context"
	"fmt"
	"io"
	"log"
	"net/http"
	"os"

	"github.com/mark3labs/mcp-go/mcp"
)

//******            使用 "github.com/mark3labs/mcp-go/mcp"创建MCP工具                           ****************************

// CreateFile 根据传入的文件路径与文件名称创建文件
// 如果参数为空，则使用默认值
// 参数：
//   - ctx: 请求的上下文
//   - request: 包含文件路径和文件名的CallToolRequest
//
// 返回值：
//   - *mcp.CallToolResult: 包含创建结果的消息
//   - error: 创建操作过程中发生的任何错误
func CreateFile(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
	log.Printf("[MCP] 调用CreateFile工具，请求参数: %+v", request.Params.Arguments)

	// 默认值设置
	defaultPath := "."
	defaultFileName := "new_file.txt"

	args, ok := request.Params.Arguments.(map[string]any)
	if !ok {
		err := fmt.Errorf("invalid arguments type")
		log.Printf("[MCP] CreateFile工具参数类型错误: %v", err)
		return nil, err
	}

	// 获取文件路径参数，如果为空则使用默认值
	filePath := defaultPath
	if pathVal, exists := args["path"]; exists {
		if strVal, ok := pathVal.(string); ok && strVal != "" {
			filePath = strVal
		}
	}

	// 获取文件名参数，如果为空则使用默认值
	fileName := defaultFileName
	if nameVal, exists := args["fileName"]; exists {
		if strVal, ok := nameVal.(string); ok && strVal != "" {
			fileName = strVal
		}
	}

	// 构建完整的文件路径
	fullPath := filePath + "\\" + fileName
	log.Printf("[MCP] CreateFile工具准备创建文件: %s", fullPath)

	// 创建文件
	file, err := os.Create(fullPath)
	if err != nil {
		errMsg := fmt.Errorf("创建文件失败: %v", err)
		log.Printf("[MCP] CreateFile工具创建文件失败: %v", errMsg)
		return nil, errMsg
	}
	defer file.Close()

	// 写入空内容（可选，os.Create已经创建了空文件）
	// 这里可以保留以确保文件确实是空的
	_, err = file.WriteString("")
	if err != nil {
		errMsg := fmt.Errorf("写入文件失败: %v", err)
		log.Printf("[MCP] CreateFile工具写入文件失败: %v", errMsg)
		return nil, errMsg
	}

	log.Printf("[MCP] CreateFile工具成功创建文件: %s", fullPath)

	return &mcp.CallToolResult{
		Content: []mcp.Content{&mcp.TextContent{Type: "text", Text: "文件创建成功" + ", 路径: " + fullPath}},
	}, nil
}

// ReadFile 读取文件并以字符串形式返回其内容。
// 参数：
//   - ctx: 请求的上下文。
//   - request: 包含文件路径的CallToolRequest。
//
// 返回值：
//   - *mcp.CallToolResult: 包含文件内容的结果。
//   - error: 读取操作过程中发生的任何错误。
func ReadFile(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
	log.Printf("[MCP] 调用ReadFile工具，请求参数: %+v", request.Params.Arguments)

	args, ok := request.Params.Arguments.(map[string]any)
	if !ok {
		err := fmt.Errorf("invalid arguments type")
		log.Printf("[MCP] ReadFile工具参数类型错误: %v", err)
		return nil, err
	}
	filePath, ok := args["path"].(string)
	if !ok {
		err := fmt.Errorf("path argument must be a string")
		log.Printf("[MCP] ReadFile工具路径参数错误: %v", err)
		return nil, err
	}

	log.Printf("[MCP] ReadFile工具准备读取文件: %s", filePath)

	content, err := os.ReadFile(filePath)
	if err != nil {
		log.Printf("[MCP] ReadFile工具读取文件失败: %v", err)
		return nil, err
	}

	log.Printf("[MCP] ReadFile工具成功读取文件: %s", filePath)

	// 使用正确的Content类型创建响应，并确保设置正确的类型字段
	return &mcp.CallToolResult{
		Content: []mcp.Content{&mcp.TextContent{Type: "text", Text: string(content)}},
	}, nil
}

// WriteFile 将字符串内容写入指定文件路径。
// 参数：
//   - ctx: 请求的上下文。
//   - request: 包含文件路径和内容的CallToolRequest。
//
// 返回值：
//   - *mcp.CallToolResult: 包含写入结果的消息。
//   - error: 写入操作过程中发生的任何错误。
func WriteFile(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
	log.Printf("[MCP] 调用WriteFile工具，请求参数: %+v", request.Params.Arguments)

	args, ok := request.Params.Arguments.(map[string]any)
	if !ok {
		err := fmt.Errorf("invalid arguments type")
		log.Printf("[MCP] WriteFile工具参数类型错误: %v", err)
		return nil, err
	}
	filePath, ok := args["path"].(string)
	if !ok {
		err := fmt.Errorf("path argument must be a string")
		log.Printf("[MCP] WriteFile工具路径参数错误: %v", err)
		return nil, err
	}

	// 处理content参数，支持多种格式
	var content string
	contentVal, exists := args["content"]
	if !exists {
		err := fmt.Errorf("content argument is required")
		log.Printf("[MCP] WriteFile工具缺少content参数: %v", err)
		return nil, err
	}

	// 尝试直接作为字符串获取
	if strVal, ok := contentVal.(string); ok {
		content = strVal
	} else if contentMap, ok := contentVal.(map[string]interface{}); ok {
		// 尝试作为对象获取，支持text字段
		if textVal, ok := contentMap["text"].(string); ok {
			content = textVal
		} else {
			err := fmt.Errorf("content object must have a string 'text' field")
			log.Printf("[MCP] WriteFile工具content对象格式错误: %v", err)
			return nil, err
		}
	} else {
		err := fmt.Errorf("content must be a string or an object with text field")
		log.Printf("[MCP] WriteFile工具content参数格式错误: %v", err)
		return nil, err
	}

	log.Printf("[MCP] WriteFile工具准备写入文件: %s", filePath)

	err := os.WriteFile(filePath, []byte(content), 0644)
	if err != nil {
		log.Printf("[MCP] WriteFile工具写入文件失败: %v", err)
		return nil, err
	}

	log.Printf("[MCP] WriteFile工具成功写入文件: %s", filePath)

	return &mcp.CallToolResult{
		Content: []mcp.Content{&mcp.TextContent{Type: "text", Text: "文件写入成功"}},
	}, nil
}

// AppendFile 将字符串内容追加到指定文件路径。
// 参数：
//   - ctx: 请求的上下文。
//   - request: 包含文件路径和内容的CallToolRequest。
//
// 返回值：
//   - *mcp.CallToolResult: 包含追加结果的消息。
//   - error: 追加操作过程中发生的任何错误。
func AppendFile(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
	log.Printf("[MCP] 调用AppendFile工具，请求参数: %+v", request.Params.Arguments)

	args, ok := request.Params.Arguments.(map[string]any)
	if !ok {
		err := fmt.Errorf("invalid arguments type")
		log.Printf("[MCP] AppendFile工具参数类型错误: %v", err)
		return nil, err
	}
	filePath, ok := args["path"].(string)
	if !ok {
		err := fmt.Errorf("path argument must be a string")
		log.Printf("[MCP] AppendFile工具路径参数错误: %v", err)
		return nil, err
	}

	// 处理content参数，支持多种格式
	var content string
	contentVal, exists := args["content"]
	if !exists {
		err := fmt.Errorf("content argument is required")
		log.Printf("[MCP] AppendFile工具缺少content参数: %v", err)
		return nil, err
	}

	// 尝试直接作为字符串获取
	if strVal, ok := contentVal.(string); ok {
		content = strVal
	} else if contentMap, ok := contentVal.(map[string]interface{}); ok {
		// 尝试作为对象获取，支持text字段
		if textVal, ok := contentMap["text"].(string); ok {
			content = textVal
		} else {
			err := fmt.Errorf("content object must have a string 'text' field")
			log.Printf("[MCP] AppendFile工具content对象格式错误: %v", err)
			return nil, err
		}
	} else {
		err := fmt.Errorf("content must be a string or an object with text field")
		log.Printf("[MCP] AppendFile工具content参数格式错误: %v", err)
		return nil, err
	}

	log.Printf("[MCP] AppendFile工具准备追加内容到文件: %s", filePath)

	// 以追加模式打开文件
	file, err := os.OpenFile(filePath, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
	if err != nil {
		log.Printf("[MCP] AppendFile工具打开文件失败: %v", err)
		return nil, err
	}
	defer file.Close()
	_, err = file.Write([]byte(content))
	if err != nil {
		log.Printf("[MCP] AppendFile工具追加内容失败: %v", err)
		return nil, err
	}

	log.Printf("[MCP] AppendFile工具成功追加内容到文件: %s", filePath)

	return &mcp.CallToolResult{
		Content: []mcp.Content{&mcp.TextContent{Type: "text", Text: "文件追加成功"}},
	}, nil
}

// DeleteFile 删除指定文件路径。
// 参数：
//   - ctx: 请求的上下文。
//   - request: 包含文件路径的CallToolRequest。
//
// 返回值：
//   - *mcp.CallToolResult: 包含删除结果的消息。
//   - error: 删除操作过程中发生的任何错误。
func DeleteFile(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
	log.Printf("[MCP] 调用DeleteFile工具，请求参数: %+v", request.Params.Arguments)

	args, ok := request.Params.Arguments.(map[string]any)
	if !ok {
		err := fmt.Errorf("invalid arguments type")
		log.Printf("[MCP] DeleteFile工具参数类型错误: %v", err)
		return nil, err
	}
	filePath, ok := args["path"].(string)
	if !ok {
		err := fmt.Errorf("path argument must be a string")
		log.Printf("[MCP] DeleteFile工具路径参数错误: %v", err)
		return nil, err
	}

	log.Printf("[MCP] DeleteFile工具准备删除文件: %s", filePath)

	err := os.Remove(filePath)
	if err != nil {
		log.Printf("[MCP] DeleteFile工具删除文件失败: %v", err)
		return nil, err
	}

	log.Printf("[MCP] DeleteFile工具成功删除文件: %s", filePath)

	return &mcp.CallToolResult{
		Content: []mcp.Content{&mcp.TextContent{Type: "text", Text: "文件删除成功"}},
	}, nil
}

// ListFiles 列出指定目录下的所有文件和子目录。
// 参数：
//   - ctx: 请求的上下文。
//   - request: 包含目录路径的CallToolRequest。
//
// 返回值：
//   - *mcp.CallToolResult: 包含文件列表的结果。
//   - error: 读取目录操作过程中发生的任何错误。
func ListFiles(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
	log.Printf("[MCP] 调用ListFiles工具，请求参数: %+v", request.Params.Arguments)

	args, ok := request.Params.Arguments.(map[string]any)
	if !ok {
		err := fmt.Errorf("invalid arguments type")
		log.Printf("[MCP] ListFiles工具参数类型错误: %v", err)
		return nil, err
	}
	filePath, ok := args["path"].(string)
	if !ok {
		err := fmt.Errorf("path argument must be a string")
		log.Printf("[MCP] ListFiles工具路径参数错误: %v", err)
		return nil, err
	}

	log.Printf("[MCP] ListFiles工具准备列出目录内容: %s", filePath)

	files, err := os.ReadDir(filePath)
	if err != nil {
		log.Printf("[MCP] ListFiles工具读取目录失败: %v", err)
		return nil, err
	}
	var fileNames []string
	for _, file := range files {
		fileNames = append(fileNames, file.Name())
	}

	log.Printf("[MCP] ListFiles工具成功列出目录内容，共%d个项目", len(fileNames))

	return &mcp.CallToolResult{
		Content: []mcp.Content{&mcp.TextContent{Type: "text", Text: fmt.Sprintf("文件列表: %v", fileNames)}},
	}, nil
}

// CreateDir 创建指定目录路径。
// 参数：
//   - ctx: 请求的上下文。
//   - request: 包含目录路径的CallToolRequest。
//
// 返回值：
//   - *mcp.CallToolResult: 包含创建结果的消息。
//   - error: 创建操作过程中发生的任何错误。
func CreateDir(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
	log.Printf("[MCP] 调用CreateDir工具，请求参数: %+v", request.Params.Arguments)

	args, ok := request.Params.Arguments.(map[string]any)
	if !ok {
		err := fmt.Errorf("invalid arguments type")
		log.Printf("[MCP] CreateDir工具参数类型错误: %v", err)
		return nil, err
	}
	filePath, ok := args["path"].(string)
	if !ok {
		err := fmt.Errorf("path argument must be a string")
		log.Printf("[MCP] CreateDir工具路径参数错误: %v", err)
		return nil, err
	}

	log.Printf("[MCP] CreateDir工具准备创建目录: %s", filePath)

	err := os.Mkdir(filePath, 0755)
	if err != nil {
		log.Printf("[MCP] CreateDir工具创建目录失败: %v", err)
		return nil, err
	}

	log.Printf("[MCP] CreateDir工具成功创建目录: %s", filePath)

	return &mcp.CallToolResult{
		Content: []mcp.Content{&mcp.TextContent{Type: "text", Text: "目录创建成功"}},
	}, nil
}

// CreateDirIfNotExist 如果目录不存在，则创建它。
// 参数：
//   - ctx: 请求的上下文。
//   - request: 包含目录路径的CallToolRequest。
//
// 返回值：
//   - *mcp.CallToolResult: 包含创建结果的消息。
//   - error: 创建操作过程中发生的任何错误。
func CreateDirIfNotExist(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
	log.Printf("[MCP] 调用CreateDirIfNotExist工具，请求参数: %+v", request.Params.Arguments)

	args, ok := request.Params.Arguments.(map[string]any)
	if !ok {
		err := fmt.Errorf("invalid arguments type")
		log.Printf("[MCP] CreateDirIfNotExist工具参数类型错误: %v", err)
		return nil, err
	}
	filePath, ok := args["path"].(string)
	if !ok {
		err := fmt.Errorf("path argument must be a string")
		log.Printf("[MCP] CreateDirIfNotExist工具路径参数错误: %v", err)
		return nil, err
	}

	log.Printf("[MCP] CreateDirIfNotExist工具准备创建目录(如果不存在): %s", filePath)

	err := os.MkdirAll(filePath, 0755)
	if err != nil {
		log.Printf("[MCP] CreateDirIfNotExist工具创建目录失败: %v", err)
		return nil, err
	}

	log.Printf("[MCP] CreateDirIfNotExist工具成功创建目录(如果不存在): %s", filePath)

	return &mcp.CallToolResult{
		Content: []mcp.Content{&mcp.TextContent{Type: "text", Text: "目录创建成功"}},
	}, nil
}

// DeleteDir 删除指定目录路径。
// 参数：
//   - ctx: 请求的上下文。
//   - request: 包含目录路径的CallToolRequest。
//
// 返回值：
//   - *mcp.CallToolResult: 包含删除结果的消息。
//   - error: 删除操作过程中发生的任何错误。
func DeleteDir(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
	log.Printf("[MCP] 调用DeleteDir工具，请求参数: %+v", request.Params.Arguments)

	args, ok := request.Params.Arguments.(map[string]any)
	if !ok {
		err := fmt.Errorf("invalid arguments type")
		log.Printf("[MCP] DeleteDir工具参数类型错误: %v", err)
		return nil, err
	}
	filePath, ok := args["path"].(string)
	if !ok {
		err := fmt.Errorf("path argument must be a string")
		log.Printf("[MCP] DeleteDir工具路径参数错误: %v", err)
		return nil, err
	}

	log.Printf("[MCP] DeleteDir工具准备删除目录: %s", filePath)

	err := os.RemoveAll(filePath)
	if err != nil {
		log.Printf("[MCP] DeleteDir工具删除目录失败: %v", err)
		return nil, err
	}

	log.Printf("[MCP] DeleteDir工具成功删除目录: %s", filePath)

	return &mcp.CallToolResult{
		Content: []mcp.Content{&mcp.TextContent{Type: "text", Text: "目录删除成功"}},
	}, nil
}

// GetFileByURL 从URL下载文件到指定路径。
// 参数：
//   - ctx: 请求的上下文。
//   - request: 包含URL和目标路径的CallToolRequest。
//
// 返回值：
//   - *mcp.CallToolResult: 包含下载结果的消息。
//   - error: 下载操作过程中发生的任何错误。
func GetFileByURL(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
	log.Printf("[MCP] 调用GetFileByURL工具，请求参数: %+v", request.Params.Arguments)

	args, ok := request.Params.Arguments.(map[string]any)
	if !ok {
		err := fmt.Errorf("invalid arguments type")
		log.Printf("[MCP] GetFileByURL工具参数类型错误: %v", err)
		return nil, err
	}
	url, ok := args["url"].(string)
	if !ok {
		err := fmt.Errorf("url argument must be a string")
		log.Printf("[MCP] GetFileByURL工具URL参数错误: %v", err)
		return nil, err
	}
	filePath, ok := args["path"].(string)
	if !ok {
		err := fmt.Errorf("path argument must be a string")
		log.Printf("[MCP] GetFileByURL工具路径参数错误: %v", err)
		return nil, err
	}

	log.Printf("[MCP] GetFileByURL工具准备从URL下载文件: %s -> %s", url, filePath)

	resp, err := http.Get(url)
	if err != nil {
		log.Printf("[MCP] GetFileByURL工具请求URL失败: %v", err)
		return nil, err
	}
	defer resp.Body.Close()
	if resp.StatusCode != http.StatusOK {
		err := fmt.Errorf("unexpected status code: %d", resp.StatusCode)
		log.Printf("[MCP] GetFileByURL工具请求URL返回非200状态码: %v", err)
		return nil, err
	}
	out, err := os.Create(filePath)
	if err != nil {
		log.Printf("[MCP] GetFileByURL工具创建目标文件失败: %v", err)
		return nil, err
	}
	defer out.Close()
	_, err = io.Copy(out, resp.Body)
	if err != nil {
		log.Printf("[MCP] GetFileByURL工具保存文件失败: %v", err)
		return nil, err
	}

	log.Printf("[MCP] GetFileByURL工具成功下载文件: %s -> %s", url, filePath)

	return &mcp.CallToolResult{
		Content: []mcp.Content{&mcp.TextContent{Type: "text", Text: "文件下载成功"}},
	}, nil
}
